﻿using Baidu.Push.Api;
using Baidu.Push.Api.Domain;
using Baidu.Push.Api.Parser;
using Baidu.Push.Api.Request;
using Baidu.Push.Api.Util;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;

namespace PushConsole
{
    public class PushMessage
    {
        public PushMessage(string desc)
        {
            this.Desc = desc;
            this.Key = PushUtils.GetCurrentTimeMillis(DateTime.Now).ToString();
        }
        public string Title { get; set; }
        public string Desc { get; set; }
        public string Key { get; set; }
        public Dictionary<string, object> CustomContent;
    }

    public enum DeviceType : uint
    {
        Browser = 1,
        PC = 2,
        Andriod = 3,
        iOS = 4,
        WindowsPhone = 5,
    }

    public static class PushHelper
    {
        /// <summary>
        /// IOS状态 1 开发状态 2 生产状态
        /// </summary>
        private static uint DEPLOY_STATUS = uint.Parse(ConfigurationManager.AppSettings["DeployStatus"]);
        private static readonly string _apiKey = ConfigurationManager.AppSettings["ApiKey"];
        private static readonly string _secretKey = ConfigurationManager.AppSettings["SecretKey"];

        public static readonly IPushClient PushClient;

        static PushHelper()
        {
            PushClient = new DefaultPushClient(_apiKey, _secretKey);
        }

        #region tag

        public static List<Tag> GetTags(string name = "")
        {
            var req = new FetchTagRequest() { Name = name };
            var res = PushClient.Execute(req);
            return res.IsError ? new List<Tag>() : res.ResponseParams.Tags;
        }

        public static bool SetTag(string tag, string user_id = "")
        {
            var req = new SetTagRequest();
            req.Tag = tag;
            req.UserId = user_id;
            var res = PushClient.Execute(req);
            return !res.IsError;
        }

        public static bool DeleteTag(string tag, string user_id = "")
        {
            var req = new DeleteTagRequest();
            req.Tag = tag;
            req.UserId = user_id;
            var res = PushClient.Execute(req);
            return !res.IsError;
        }

        public static List<Tag> QueryUserTags(string user_id)
        {
            var req = new QueryUserTagsRequest() { UserId = user_id };
            var res = PushClient.Execute(req);
            return res.IsError ? new List<Tag>() : res.ResponseParams.Tags;
        }

        #endregion

        #region push

        public static int PushMessage(string user_id, PushMessage msg)
        {
            var user = PushClient.GetBindItem(user_id);
            return user != null ? PushClient.PushMessage(user, msg) : 0;
        }

        public static int PushNotification(string user_id, PushMessage msg)
        {
            var user = PushClient.GetBindItem(user_id);
            return user != null ? PushClient.PushNotification(user, msg) : 0;
        }

        #endregion

        #region Extension

        public static QueryBindItem GetBindItem(this IPushClient client, string user_id)
        {
            var req = new QueryBindlistRequest();
            req.UserId = user_id;
            var res = client.Execute(req);
            return res.IsError ? null : res.ResponseParams.Binds.FirstOrDefault();
        }

        /// <summary>
        /// 推送消息
        /// </summary>
        public static int PushMessage(this IPushClient client, QueryBindItem user, PushMessage msg)
        {
            //IOS仅支持通知
            if (user.DeviceType == (uint)DeviceType.iOS) return client.PushNotification(user, msg);

            var req = new PushMsgRequest();

            req.UserId = user.UserId;
            req.DeviceType = user.DeviceType;
            req.PushType = 1;
            req.MsgKeys = msg.Key;
            req.Messages = msg.Desc;

            if (user.DeviceType == (uint)DeviceType.Andriod)
            {
                //Android可以指定某一个特定client
                req.ChannelId = user.ChannelId;
            }

            var res = client.Execute(req);
            return res.IsError ? 0 : res.ResponseParams.SuccessAmount;
        }

        /// <summary>
        /// 根据user推送通知
        /// </summary>
        public static int PushNotification(this IPushClient client, QueryBindItem user, PushMessage msg)
        {
            var req = new PushMsgRequest();

            req.UserId = user.UserId;
            req.DeviceType = user.DeviceType;
            req.PushType = 1;
            req.MessageType = 1;
            req.Messages = GetNotification((DeviceType)user.DeviceType, msg);
            req.MsgKeys = msg.Key;

            if (user.DeviceType == (uint)DeviceType.Andriod)
            {
                //Android可以指定某一个特定client
                req.ChannelId = user.ChannelId;
            }
            else if (user.DeviceType == (uint)DeviceType.iOS)
            {
                //IOS需指定部署状态
                req.DeployStatus = DEPLOY_STATUS;
            }

            var res = client.Execute(req);
            return res.IsError ? 0 : res.ResponseParams.SuccessAmount;
        }

        /// <summary>
        /// 根据标签推送消息
        /// </summary>
        public static int PushMessageByTag(this IPushClient client, DeviceType deviceType, PushMessage msg, string tag)
        {
            //IOS仅支持通知
            if (deviceType == DeviceType.iOS) return client.PushNotificationByTag(deviceType, msg, tag);

            var req = new PushMsgRequest();
            req.Tag = tag;
            req.DeviceType = (uint)deviceType;
            req.PushType = 2;
            req.MessageType = 0;
            req.MsgKeys = msg.Key;
            req.Messages = msg.Desc;
            var res = client.Execute(req);
            return res.IsError ? 0 : res.ResponseParams.SuccessAmount;
        }

        /// <summary>
        /// 根据标签推送通知
        /// </summary>
        public static int PushNotificationByTag(this IPushClient client, DeviceType deviceType, PushMessage msg, string tag)
        {
            var req = new PushMsgRequest();
            req.Tag = tag;
            req.DeviceType = (uint)deviceType;
            req.PushType = 2;
            req.MessageType = 1;
            req.MsgKeys = msg.Key;
            req.Messages = GetNotification(deviceType, msg);
            if (deviceType == DeviceType.iOS) req.DeployStatus = DEPLOY_STATUS; //IOS需指定部署状态
            var res = client.Execute(req);
            return res.IsError ? 0 : res.ResponseParams.SuccessAmount;
        }

        /// <summary>
        /// 推送消息给所有人
        /// </summary>
        public static int PushAllMessage(this IPushClient client, DeviceType deviceType, PushMessage msg)
        {
            //IOS仅支持通知
            if (deviceType == DeviceType.iOS) return client.PushAllNotification(deviceType, msg);
            var req = new PushMsgRequest();
            req.DeviceType = (uint)deviceType;
            req.PushType = 3;
            req.MessageType = 0;
            req.MsgKeys = msg.Key;
            req.Messages = msg.Desc;
            var res = client.Execute(req);
            return res.IsError ? 0 : res.ResponseParams.SuccessAmount;
        }

        /// <summary>
        /// 推送通知给所有人
        /// </summary>
        public static int PushAllNotification(this IPushClient client, DeviceType deviceType, PushMessage msg)
        {
            var req = new PushMsgRequest();
            req.DeviceType = (uint)deviceType;
            req.PushType = 3;
            req.MessageType = 1;
            req.MsgKeys = msg.Key;
            req.Messages = GetNotification(deviceType, msg);
            if (deviceType == DeviceType.iOS) req.DeployStatus = DEPLOY_STATUS; //IOS需指定部署状态
            var rsp = client.Execute(req);
            return rsp.IsError ? 0 : rsp.ResponseParams.SuccessAmount;
        }

        #endregion

        #region GetNotificationString

        internal static string GetNotification(DeviceType deviceType, PushMessage msg)
        {
            return GetNotification(deviceType, msg.Title, msg.Desc, msg.CustomContent);
        }

        internal static string GetNotification(DeviceType deviceType, string title, string desc, Dictionary<string, object> dic)
        {
            if (deviceType == DeviceType.Andriod)
            {
                var android = new AndroidNotification();
                android.Title = title;
                android.Description = desc;
                android.NotificationBuilderId = 0;
                android.NotificationBasicStyle = 0x07;
                android.CustomContent = dic;
                return PushJsonParser.Serialize(android);
            }
            else
            {
                if (dic == null) dic = new Dictionary<string, object>();
                if (!string.IsNullOrEmpty(title)) dic["title"] = title;
                dic["description"] = desc;
                return PushJsonParser.Serialize(dic);
            }
        }

        #endregion
    }
}
